home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
10,000 Great Games
/
10,000 Great Games.iso
/
Product
/
66
/
data1.cab
/
Source_Files
/
Src
/
Bitmap.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-16
|
6KB
|
323 lines
#include "stdafx.h"
cBMP *bitmaps = 0;
cBMP::cBMP(int _w, int _h, char *_name)
{
// Set variables
w = _w;
h = _h;
usedcount = 0;
dds_vid = 0;
// Set name
name = strdup(_name);
// Create surface
if ((dds = create_surface(w, h, DDSCAPS_SYSTEMMEMORY, DDSD_CKSRCBLT)) == 0)
error("Unable to create surface for %s", name);
// Add image to list
add((cList **)&bitmaps);
}
cBMP::~cBMP()
{
free(name);
safe_release(&dds);
safe_release(&dds_vid);
}
void cBMP::reset()
{
for (cBMP *b = bitmaps; b != 0; b = (cBMP *)b->next)
{
safe_release(&b->dds_vid);
b->usedcount = 0;
}
}
LPDIRECTDRAWSURFACE4 cBMP::bestptr(cSurface *dest)
{
// If we don't have the caps don't bother putting things in video memory
if (no_blit_hardware || !hardware_blit_caps || (dest->caps.dwCaps & DDSCAPS_SYSTEMMEMORY))
return dds;
// Increase usedcount
usedcount++;
// Resort, least used images first
sort(&this_minus_other_usedcount);
// Return pointer
return dds_vid != 0? dds_vid:dds;
}
int cBMP::this_minus_other_usedcount(cList *t, cList *o)
{
return ((cBMP *)t)->usedcount - ((cBMP *)o)->usedcount;
}
void cBMP::make_dynamic_use_of_video_mem()
{
// If we don't have the right blit caps then don't bother putting things in video memory
if (no_blit_hardware || !hardware_blit_caps)
return;
// Get end of list
cBMP *e = (cBMP *)cList::get_end((cList *)bitmaps);
// No images or none ever used
if (e == 0 || e->usedcount <= 0)
return;
// Try to find an image that could be blit to video memory
for (; e != bitmaps && e->dds_vid != 0; e = (cBMP *)e->prev);
// All images are in video memory or no more used images, good!
if (e == bitmaps || e->usedcount <= 0)
return;
// Allocate image
e->dds_vid = create_surface(e->w, e->h, DDSCAPS_VIDEOMEMORY, DDSD_CKSRCBLT);
if (e->dds_vid != 0)
{
// Image created, now blit the contents to video memory
while (FAILED(e->dds_vid->BltFast(0, 0, e->dds, 0, DDBLTFAST_WAIT)))
if (FAILED(e->dds->Restore()) || FAILED(e->dds_vid->Restore()))
{
// Some resource permanently lost
safe_release(&e->dds_vid);
// Exit loop
break;
}
return;
}
// Not enough room to allocate surface, search for least used image in video memory
for (cBMP *b = bitmaps; b != e && b->dds_vid == 0; b = (cBMP *)b->next);
// Is there one?
if (b == e)
{
// No room for this image, make it very unimportant and resort it
e->usedcount = -100;
e->relink((cList **)&bitmaps);
return;
}
// Release this image
safe_release(&b->dds_vid);
}
static void create_add_file(const char *fn, const char *name)
{
// Read the bitmap headers into memory
CFile b;
if (!b.Open(fn, CFile::modeRead | CFile::shareDenyWrite))
error("Unable to open %s", fn);
BITMAPFILEHEADER bfh;
b.Read(&bfh, sizeof(bfh));
BITMAPINFOHEADER bih;
b.Read(&bih, sizeof(bih));
// Check if it's in the right format
if (bfh.bfType != 'MB')
error("Bitmap %s is not a bitmap", fn);
if (bih.biHeight <= 0)
error("Bitmap %s is not bottom up", fn);
if (bih.biBitCount != 8)
error("Bitmap %s is not 8 bit", fn);
if (bih.biCompression != BI_RGB)
error("Bitmap %s is compressed!", fn);
// Get width of scanline
int w = (bih.biWidth + 3) & ~3;
// Read bitmap data
char *d = new char [bih.biHeight * w];
b.Seek(bfh.bfOffBits, CFile::begin);
b.Read(d, bih.biHeight * w);
// Open database file
CFile f;
if (!f.Open("Bitmaps.dat", CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::shareExclusive))
error("Unable to open Bitmaps.dat");
f.SeekToEnd();
// Write name of object + bytecount of string
int l = strlen(name);
f.Write(&l, sizeof(l));
f.Write(name, l);
// Write bitmap width and height
f.Write(&bih.biWidth, sizeof(bih.biWidth));
f.Write(&bih.biHeight, sizeof(bih.biHeight));
// Write data
for (int y = bih.biHeight - 1; y >= 0; y--)
f.Write(&d[w * y], bih.biWidth);
// Release temporary space
delete d;
}
void cBMP::create_file()
{
search_files("Bmp", "*.BMP", create_add_file);
}
void cBMP::load()
{
BYTE *data, *d, *s;
int l, x, y, w, h;
char name[256];
CFile f;
// Open bitmaps file
if (!f.Open("Bitmaps.dat", CFile::modeRead | CFile::shareDenyWrite))
error("Unable to open Bitmaps.dat");
while (f.Read(&l, sizeof(l)) == sizeof(l))
{
// Read name
f.Read(name, l);
name[l] = 0;
// Read dimensions
f.Read(&w, sizeof(w));
f.Read(&h, sizeof(h));
// Read bitmap data
data = new BYTE [w * h];
f.Read(data, w * h);
// Create bitmap
cBMP *b = new cBMP(w, h, name);
// Lock the surface for writing bitmap data
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);
if (FAILED(b->dds->Lock(0, &ddsd, DDLOCK_WAIT, 0)))
error("Unable to lock memory for bitmap load");
// Copy data
s = (BYTE *)ddsd.lpSurface;
d = data;
switch(ddsd.ddpfPixelFormat.dwRGBBitCount)
{
case 8:
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++, s++, d++)
*s = color_table_this_mode[*d];
s += ddsd.lPitch - w;
}
break;
case 16:
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++, s += 2, d++)
*(WORD *)s = color_table_this_mode[*d];
s += ddsd.lPitch - (w << 1);
}
break;
case 24:
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++, s += 3, d++)
*(WORD *)s = color_table_this_mode[*d],
s[2] = color_table_this_mode[*d] >> 16;
s += ddsd.lPitch - (w << 1) - w;
}
break;
case 32:
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++, s += 4, d++)
*(DWORD *)s = color_table_this_mode[*d];
s += ddsd.lPitch - (w << 2);
}
break;
}
// Unlock memory
b->dds->Unlock(0);
// Release data
delete data;
}
}
cBMP *cBMP::get(char *fn)
{
for (cBMP *b = bitmaps; b != 0; b = (cBMP *)b->next)
if (eq(fn, b->name))
return b;
error("Image %s not found", fn);
return 0;
}